← OnWeight HQLogic & Flows

OnWeight — Source of Truth: Logic, Formulas & Flows

Status legendDocumented — taken directly from the Figma frames / spec table. 🟡 Assumed — a reasonable rule I've proposed to make the prototype compute; needs your confirmation. 🔴 Open — not yet specified anywhere; decision required.

Last updated from: Key user flows, Goal Setting Flow, WeeklyLossRate, CutStrategy, MenstrualCycleWeightChanges, Trending Weight & Phases, the per-sport GS_14A_* frames, and the sport rules table.


1. Purpose

OnWeight helps a combat athlete cut to their fight-day weight safely and on schedule. The app's job is to interpret daily weigh-ins — telling the athlete in plain language whether they are on track, then exposing the underlying numbers for those who want them.

The core intelligence is three layers:

  1. Trend — smooth noisy daily weigh-ins into a true trajectory.
  2. Projection — extrapolate that trajectory to weigh-in day.
  3. Verdict — classify pace (safe vs too fast vs behind vs off-track) and coach accordingly.

2. Inputs & data model

2.1 Athlete profile (set in onboarding)

FieldSourceNotes
biologicalSexSignUp_BiologicalSexGates menstrual-cycle flow + some strategy warnings. Also selects the division ladder (divisions.men / divisions.women) via recommendDivision(sport, wt, sex) — map female → 'women', else 'men'.
currentWeight (kg)SignUp_CurrentWeightInputStarting / walk-around weight.
goalWeight (kg)SignUp_GoalWeightInputThe athlete's target fight-day body weight. User-facing term is now "your limit" — the weight you must hit on the scale (the onboarding screen reads "Your limit", not "Goal weight"). The field / code name stays goalWeight; only the athlete-facing copy changed. See the Lexicon note in §18.
sportSignUp_SelectSportBoxing / Muay Thai / BJJ (gi/no-gi) / Taekwondo / Judo / MMA.
hasFight + fightDateSignUp_Date_Fight / SignUp_NoFightNo-fight users get an open-ended plan.
weighInPreference (time of day)GS_02_WeighInTimePreferenceWhen the daily fasted weigh-in reminder fires.
morningNotifGS_03_MorningNotifOptInOpt-in to the reminder.
cutRate (% bw/week)WeeklyLossRateSee §5.
cutStrategies[]CutStrategyFight-week tactics. See §8.
Cycle settingsGS_09AGS_13ASee §7.

2.2 Competition rules (per sport — auto-filled, user-confirmable)

Source: ✅ sport rules table + GS_14A_CheckSportDetails_*, GS_15AGS_21A.

SportEquipment req.Equipment weightRe-weigh-inHydration clauseHydration capWeigh-in timing
Boxingnon/anonon/aSame day (amateur), day before (pro)
Muay Thainon/anonon/aSame day (amateur), day before (pro)
BJJ (no gi)yes0.5 kg (rashguard + pants)nonon/aWithin 2 hours
BJJ (gi)yes1.2 kgnonon/aWithin 2 hours
Taekwondoyes1.2 kgyes (5%)non/aDay before (with re-weigh-in 5%)
Judoyes1.2 kgyes (5%)non/aDay before (with re-weigh-in 5%)
MMAnon/anonon/aDay before

Note (✅): any non-equipment sport weighs in in underwear only. Hydration-clause fields exist in the model (GS_20A/GS_21A) for promotions that test hydration, even though none of the default sports above enable it.

2.3 Daily log


3. Target-weight calculation

The number the athlete must hit on the scale is not always their goal body weight — equipment and weigh-in timing change it.

`` scaleTarget = divisionLimit // the official class limit bodyTarget = scaleTarget − equipmentWeight // what the BODY must weigh (equipmentWeight = 0 for underwear-only sports) ``

3.1 Re-weigh-in (Taekwondo, Judo)

✅ A second weigh-in caps rehydration: the athlete may not exceed +5% of the division limit at re-weigh. This limits how aggressively they can dehydrate, because they must be able to recover within the cap.

3.2 Weigh-in timing → rehydration window

✅ Documented per sport; 🟡 implication for the cut:

🟡 Proposed rule: weigh-in timing sets the maximum safe fight-week water cut and therefore how much of the gap can be left to fight week vs. must be lost as true weight during camp.

3.3 Out-of-healthy-range guard (±20 kg) ✅ (built — GoalOutOfRange)

When the entered limit is more than ~20 kg from current weight (either direction), the goal step raises a calm "Out of healthy range" gate instead of silently building a plan: it names the risk plainly ("This target looks like a mistake"), points the athlete to a doctor + sports dietitian, and states that OnWeight won't build an aggressive plan toward an unsafe target. A "Keep it anyway" branch lets the athlete proceed against advice (they own the number), but the recommendation and tone stay conservative. Within ±20 kg there is no popup. Lives in fc-strategy-info.jsx; see §18.


4. Trend & projection (the engine)

4.1 Trend smoothing ✅ (implemented)

Daily weigh-ins are noisy (water, food, glycogen). The displayed trend is a 5-day exponentially-weighted moving average:

`` trend[i] = Σ ( weight[i-k] · 0.75^k ) / Σ ( 0.75^k ) for k = 0..4 ``

4.2 Velocity ✅

`` weeklyVelocity = 7-day change in the trend // kg/week, negative = losing dailyVelocity = weeklyVelocity / 7 ``

4.3 Projection ✅ (implemented, linear)

`` daysToWeighIn = campDays − todayDay projected = trendingToday + dailyVelocity × daysToWeighIn // TRUE-weight projection gap = projected − bodyTarget // + = will be over the limit toGo = trendingToday − bodyTarget // kg still to lose from today ``

🟡 Currently a straight-line extrapolation of current pace. A more honest model would project along the planned rate (the chosen cutRate) and flag divergence — see §6.

4.4 Cycle-aware projection ✅ (implemented) — the weigh-in buffer

The number that matters is what the scale reads on weigh-in day, not the athlete's underlying true weight. If weigh-in lands in a water-retention phase (luteal), the scale reads higher than true weight — so the plan must pre-cut extra true weight as a buffer.

`` weighInOffset = cycleOffsetKg(weighInDay) // §7 — kg the scale reads above true weight that day projectedScale = projected + weighInOffset // honest scale reading at weigh-in cycleBuffer = max(0, weighInOffset) // extra TRUE weight to pre-cut trueTarget = bodyTarget − cycleBuffer // the true-weight number the plan aims at scaleGap = projectedScale − bodyTarget // the gap that actually decides made/missed ``


5. Cut-rate strategy (the pace thresholds) ✅

Source: WeeklyLossRate. Rates are % of body weight per week:

OptionRateGuidance
Maximum1.0% / wkBeyond this, muscle loss is likely, impacting strength & power. (Hard ceiling.)
Aggressive0.75% / wkEffective but may impact performance during camp.
Recommended0.5% / wkOptimal — preserves muscle, supports strong performance.
Conservative0.25% / wkSlow & steady; minimal performance impact, needs a longer timeline.

`` plannedWeeklyLossKg = currentWeight × (cutRate / 100) ``


6. Pace classification — the gauge

Source: Trending Weight & Phases shows a 4-zone gauge: Low · On Track · High · Risk, evaluated on the 7-day average. This maps to the four feedback screens (AW_08AAW_8D).

Gauge zoneMeaningFeedback screenTone
On TrackLoss rate ≈ planned; projection lands at/under targetAW_08A_OnTrackgreen
LowLosing too slowly; projection misses target but recoverableAW_08C_SlowProgressamber
Risk (slow)So far behind it isn't safe to make weight at ≤1%/wkAW_8D_NotOnTrack_CTAred
HighLosing faster than planned; over-cuttingAW_08B_TooFastamber

🟡 Proposed thresholds (NEED CONFIRMATION). Let r = current 7-day-avg loss as % bw/wk and target = chosen cutRate:

🔴 Confirm the exact boundary numbers and whether the gauge is driven purely by rate (r) or by projected gap, or a blend of both.


7. Menstrual-cycle adjustments 🟢 (evidence-based defaults — now sourced) — drives the math, learns per athlete

Source: GS_13A_MenstrualCycleWeightChanges + a literature review (2024–25). Shown only when biologicalSex = female and the athlete opts in (GS_09A). All values are customisable defaults; contraceptive users may set all to 0; athletes with absent/irregular cycles are handled separately (§7.4).

What the evidence says (replaces the old guesses).

7.1 The water-weight curve ✅ (implemented)

One smooth curve is the single source of truth for every cycle chart and the projection (§4.4), so they can never disagree. Water offset (kg the scale reads above true weight) follows a cosine over the cycle: it dips to −retention in follicular (~day 10) and peaks at +retention in late luteal (~day 24).

`` cycleDayAt(campDay) = (dayToday + (campDay − todayDay)) mod cycleLength cycleOffsetKg(campDay) = retention × −cos( 2π · (cycleDayAt − 10) / cycleLength ) cyclePhaseAt(campDay): <5 menstrual · <13 follicular · <16 ovulation · else luteal ``

Model offset (cosine, around the cycle mean):

PhaseWhenModel offset at phase centreNote
Menstruationdays 0–5~0 kg (falling off the luteal peak)puffiness often lingers day 1–2
Folliculardays 5–13−retention (≈ −0.5 kg)water low — lightest readings
Ovulationdays 13–16~0 kg (rising)
Lutealdays 16–28+retention (≈ +0.5 kg)water retention — heaviest readings

User-facing onboarding defaults (simplified, relative to baseline, all editable): Luteal +0.5, Menstruation +0.3, Follicular 0, Ovulation 0. retention is the peak amplitude (default 0.5 kg). The slight framing difference (cosine-around-mean vs. baseline-relative phase numbers) is intentional: the curve drives the math; the phase numbers are the human-editable view.

7.2 How it feeds logic ✅

7.3 Personalisation from logged data ✅ (designed) — Learned from your data screen

The per-phase amplitude is a starting estimate, then learned per athlete. Once ~2–3 cycles are logged, fit each athlete's real luteal amplitude from the cyclic residual of their weigh-ins (the swing left after removing the downward cut trend) and recommend an update (e.g. default +0.5 → measured +0.8). The athlete accepts or keeps the default — never silent.

🟡 Caveats to honour in the model: (1) needs ≥2–3 cycles; (2) the cut trend confounds the cyclic signal — must separate trend from residual; (3) round conservatively and label it a personalised estimate, not medical advice.

7.4 Absent / irregular cycles ✅ (designed) — Cycle Regularity screen (Refine step 4)

Hard camps and aggressive cuts frequently disrupt or stop periods. Captured as Regular / Irregular / Not currently:

✅ The prototype now uses the evidence-based default (luteal peak +0.5, follicular −0.5, amplitude retention = 0.5), personalised from data and always overridable. This resolves the old +2.0 / +1.0 / −1.0 discrepancy and the F8 menstruation-note contradiction (menstruation now carries a small positive lingering hold, consistent with the "may rise" note).


7b. Weigh-in time & consistency ✅ (implemented)

The daily fasted weigh-in is only comparable day-to-day if it's taken at a consistent time. The app treats consistency as the priority and first-thing-fasted as the accuracy ideal.

7b.1 Preference (weighInTime, weighInTargetHour)

7b.2 Per-entry time ✅

7b.3 Double weigh-ins ✅ (canonical rule)


8. Fight-week cut strategies ✅

Source: CutStrategy. These are fight-week tactics, separate from the daily camp cut rate.

StrategyEffectRecommendation
Low Fibre DietFlush gut, ~1% of scale weightRecommended
Low Sodium Diet2–3 days, ~0.5–1% water weightRecommended
Sweat OutSauna/sweat⚠️ Never more than 5% of bodyweight
Low CarbGlycogen depletion❌ Not recommended — 24 h to reload, fuels performance
Water LoadManipulate water, temp. ~0.5% drop❌ Not recommended for female athletes

🟡 Selected strategies define the fight-week portion of the cut (the water/manipulation buffer), which combines with the camp's true-weight loss to reach scaleTarget. Total water-cut should respect the per-strategy ceilings (esp. Sweat Out ≤5%) and the re-weigh cap (§3.1).


9. Adaptive weekly goal & the tracking cascade

✅ Documented as a flow ("Log weight → adaptive weekly goal updates → feedback"; "Edit Plan → recalculated targets") and shown per-week in Weeks (Check-ins x/7, Tracking Weight, Weekly Loss %, Average weight loss kg).

9.1 The tracking cascade ✅ (CONFIRMED — evidence-based, sports-dietitian + research review)

Principle: daily scale weight is mostly water/gut noise and is stressful for athletes to interpret. We never judge a cut on a raw daily reading. We escalate through timescales, and every comparison is against the cycle-adjusted expected line (§7), never a raw straight line.

The evidence that sets the thresholds. Within-subject day-to-day body-mass SD is ~0.5 % of bodyweight under standardised weighing (≈0.4 kg at 78 kg), and larger free-living (2-wk change SD ≈1.1–1.3 kg; ~630 kcal/day intake swing ≈ 1 kg). Averaging only cuts noise by √n, so:

Windowresidual noise (1 SD)true loss in window @0.5–1 %/wk
1 day0.4–0.8 kg0.06–0.11 kg
3-day avg0.23–0.46 kg0.17–0.34 kg
7-day avg0.15–0.30 kg0.39–0.78 kg

A 3-day average's own noise is as big as the signal AND bigger than a ±200 g band, so a ±200 g pass/fail on 3 days misclassifies ~⅓–½ of the time. The signal only clears the noise at the 7-day rate (and 7-day-vs-prior-7-day). Therefore:

Step 0 — Displayed trend weight. The only weight the athlete sees as a verdict is a 7-day-equivalent smoothing (EWMA, smooth()), never the raw daily number. Raw daily is logged, charted as dots, but carries no verdict.

Step 1 — Daily silent gate. If today's reading is within ±200 g of the cycle-adjusted expected weight → silently "fine", stop. Off it → escalate silently (no alarm, no red).

Step 2 — 3-day provisional filter. 3-day trailing average within ±0.4 kg (≈0.5 %, matched to its real noise — not 200 g) of the cycle-adjusted expected weight → treat as noise, on track. Else → go to the rate check.

Step 3 — 7-day rate verdict. Compare the last-7-day vs prior-7-day true-weight rate (cycle-water removed). Requires ≥4 logged days per window; with <14 days of data, fall back to an all-data regression. This rate drives the on-track / cutting-fast / behind verdict.

Symmetry. Being under the line (losing too fast) flags the same way as being over — but the response differs: too-fast → add food back; behind → tighten. (Voice per §11.)

9.2 Two independent re-plan triggers ✅

A "Change your plan" flow launches when either:

Anti-flapping: separate enter/exit thresholds and a 2-reading confirmation before the flow is offered, so the athlete is never bounced in and out of "off track".

9.3 Weekly goal recalculation ✅

Each week, re-derive the remaining required pace from the current trend so the plan self-corrects: `` weeksLeft = daysToWeighIn / 7 requiredWeekly = (trendingToday − trueTarget) / weeksLeft // trueTarget already cycle-buffered (§4.4) nextWeekGoalKg = clamp(requiredWeekly, 0, currentWeight × 1%) // never exceed the 1%/wk ceiling nextWeekGoalKg −= Δphase_nextWeek // cycle offset (§7) ` If requiredWeekly` would exceed the 1 %/wk ceiling, don't silently cap and carry on — fire re-plan trigger (A). Missed check-ins: a window with <4 logs holds the prior verdict rather than guessing.

9.4 Cycle amplitude default ✅

Population default water amplitude = 0.5 kg (evidence: ~0.45–0.5 kg average premenstrual gain, fluid not fat; many women see none, some up to ~1.4–2.3 kg). Individualised from the athlete's own logged residuals (§15.4), learned upward or downward. Never assume a large swing for everyone.

9.5 Two-tier detection — drift-watch (early) + confirmed verdict (late) ✅ (CONFIRMED — evidence + detection-theory review)

The problem the dietitian raised: a 7-day rate is statistically sound but slow — for a fighter on a tight deadline, "by day 7 it's too late." Lost runway can't be recovered.

The resolution (not a binary): a 7-day window is rolling — it updates every day, not a checkpoint you wait for; and we layer a faster early-warning tier on top. Detection theory is clear there's an unavoidable trade between detection delay and false-alarm rate, so we place that trade deliberately: early + soft (high sensitivity, off the alarm channel) → confirmed + hard (high specificity, drives the re-plan flow).

TierMethodSpeedSurfaced asCan fire re-plan?
TrendEWMA (smooth()) — recent days weighted heaviestbends in ~2–3 daysthe only weight shownno
Drift-watchCUSUM of daily deviation vs cycle-adjusted line (driftWatch())catches consistent drift in ~2–3 daysquiet, non-red noteno (soft only)
Confirmed verdict7-day rolling rate + daily projection (§9.1, §9.2)confirmed, low false-alarmthe verdict + Change-planyes

Why EWMA, not a flat average. An EWMA "will detect shifts of 0.5σ to 2σ much faster than a simple chart with the same sample size" because recent data is weighted heaviest. Responsiveness is tunable via the smoothing factor (β high = smoother/slower, β low = faster/noisier).

Why CUSUM for the early tier. A one-sided cumulative sum S = max(0, S + (deviation − k)) accumulates small same-direction deviations "to achieve the effect of amplification," making a persistent drift visible "much faster" than a windowed average — while the slack k (~0.15 kg/day) absorbs ordinary water noise so a single bad-water morning never trips it. It is soft-only: it opens a watch, never the re-plan flow.

Deadline-tightening (context-driven). The CUSUM decision limit h shrinks as fight day nears (h = 0.85 → 0.65 → 0.45 kg at >28 / ≤28 / ≤14 days out). A fighter's costs are asymmetric — a missed "you're behind" is far worse than an extra soft nudge — so we buy faster detection late, when lost runway is most expensive, at the price of a few more (still non-alarming) watches.

Two protections that matter more than raw detection speed:

Symmetry. Drift-watch runs two-sided: behind (losing too slow) and fast (losing too quick) trip independently, each with its own supportive response (§11).


10. Key user flows ✅

The app is paywalled end to end — there is no free tier and no Pro tier. First-run is therefore one funnel with one hinge: the paywall. Before it, the job is convert; after it, activate. (The earlier Free-Onboarding / Pro-Goal-Setting tier split is retired — those tiers don't exist.) See OnWeight - Onboarding & Goal Setting Flows.html for the strategy + visual map (the prior tier-based map is preserved as …Flows v1.html); live screens are in OnWeight - All Screens.html.

Flow 1 · Onboarding (pre-paywall)prove value, earn the subscription (eyebrow "OnWeight Setup"). Six high-signal questions, each reshaping the plan; account & permissions deferred.

Launch → Sport → (Fight date | No fight) → Biological sex → Current weight → Goal weight → Cut rate → Building your camp → Coach's Read → Plan Preview · Paywall

Each pre-paywall question must change the plan or be cut. The Coach's Read is the engineered "aha" before price; the paywall delivers a plan the athlete watched build, headline echoing their own numbers. The hinge: subscribe → create account to save the camp → setup. A hard paywall has no free-home fallback — declining ends the session, so re-engagement (reminder / email / win-back) is the only recovery path and must be built. (Trial vs hard-paid: still open — recommend a free trial; longer trials convert materially better.)

Flow 2 · Set up camp (post-paywall)precision, then a first win (eyebrow "Set up your camp", no tier pill). Friction acceptable; the new-user experience runs to the first logged weigh-in. `Weigh-in time → Morning reminder (push opt-in, deferred) → [if female & opted-in] Cycle on? → Period date → Cycle length → Phase weight changes → Confirm competition rules (equipment, equipment weight, re-weigh-in + buffer, hydration clause/cap) → Cut strategies → Check details → Refining plan →

Choose plan shape (Tapered | Linear) → Log first weigh-in → Home`

Cut strategies moved here (fight-week detail, not a conversion lever). Account creation happens at purchase; the notification permission is deferred to Step 2. The cycle sub-flow is gated on biologicalSex = female (captured pre-paywall) and the opt-in; otherwise it skips straight to competition rules. Every cycle screen is independently skippable. Ends on the first weigh-in — the activation milestone that predicts retention.

Log weight (Home quick action or Logbook) Enter weight → pick date → Save → recompute trend + projection → adaptive weekly goal update → Feedback screen (On Track / Too Fast / Slow / Off-track CTA)

Edit Plan Change fight date / weigh-in / division / equipment / cycle settings → recalculated targets

Browse Learn → watch video / read article → (optional) save.

View Strategy Guidance → what's generally recommended / NOT for your sport & weigh-in timing.


11. Prototype reconciliation (what to change)

When wiring the prototype to this spec:

  1. Pace states → computed. Replace the four hand-picked PACE_STATES presets with a classifier that takes one weight series + cutRate and derives the gauge zone via §6 thresholds.
  2. Cycle defaults — ✅ resolved. The build now runs the evidence-based default retention = 0.5 kg (§7/§14.3), personalised from logged data and always overridable. The old +2.0/−1.0 guesses and the "§7 is OPEN" hold are retired.
  3. Add onboarding decisions that actually feed logic: cutRate (§5) and per-sport rules (§2.2) driving bodyTarget (§3).
  4. Projection — ✅ cycle-aware scale projection + projection cone added (§4.4). Optionally also switch the central line to plan-relative.
  5. Adaptive goal — implement §9 once the recalculation rule is confirmed.
  6. New Trend-tab instruments — ✅ projection cone (§4.4), cut burndown (kg-to-go vs days-to-go), weigh-in time-drift scatter (§7b), and the cycle-adjusted plan chart (§7.2). All theme/tone-aware.

12. Open questions — ✅ now resolved in §14

These were parked; all six are now answered against the literature + governing-body rules in §14. The values there are evidence-based defaults, still user-overridable.


13. ⚠️ Rules that don't fully hold up (flagged for review)

Things that are internally inconsistent, ambiguous, or look risky as written. None are blocking, but they should be resolved before this logic is trusted in a build.


14. Research-backed resolutions ✅ (June 2026)

The open questions in §12 and several flags in §13 are resolved below against sports-science literature and governing-body rules. Numbers are defaults, not medical advice — every value stays user-overridable, but these are the evidence-based starting points.

Sources (combat-sport weight-cutting science): Reale, Slater & Burke, Acute-weight-loss / rapid-weight-loss reviews (IJSNEM); Ruiz-Castellano et al. 2021, Achieving an Optimal Fat Loss Phase in Resistance-Trained Athletes (Nutrients); Hagmar et al. & Stachenfeld, menstrual-cycle fluid balance; ACSM/IOC weight-management position stands; governing bodies: IJF SOR, World Taekwondo, IBJJF, UFC / ABC Unified Rules, IBA / USA Boxing.

14.1 Safe cut-rate & the gauge (resolves Q-gauge, F1, F2, F3)

red zone at ≥ 1.0 %/wk.

  1. Projection — will the cone (§4.4) land at/under the limit by weigh-in? (the "behind / off-track" signal). "Dangerously behind" and "dangerously fast" are different signals and must not share one bar.
  2. Thresholds (defaults): let r = 7-day loss %bw/wk, target = chosen cutRate.
  3. On track: target−0.15 ≤ r ≤ target+0.20 and projection cone clears the limit.
  4. Too fast (amber): target+0.20 < r < 1.0.
  5. Unsafe fast (red): r ≥ 1.0 (the ceiling — muscle-loss zone).
  6. Behind (amber): projection misses but the gap is still closable by date at ≤ 1.0 %/wk.
  7. Off-track (red): gap cannot be closed by the date at ≤ 1.0 %/wk → feasibility CTA (§14.6).

14.2 Adaptive weekly goal & total-cut ceiling (resolves Q-adaptive, F5)

14.3 Menstrual-cycle defaults (resolves Q-cycle)

14.4 Division limits & equipment direction (resolves Q-limits, F9, F10)

divisionLimit − equipmentWeight` (the body must come in lighter).

14.5 Same-day weigh-in needs a different plan type (resolves Q-sameday, F6)

14.6 Feasibility warning (resolves Q-feasibility)

At onboarding and on every plan edit: `` requiredAvgWeekly = (currentWeight − bodyTarget) / weeksToWeighIn // off current weight infeasible = requiredAvgWeekly > currentWeight × 1.0% // can't be done safely veryHighCut = (currentWeight − bodyTarget) / currentWeight > 0.10 // >10% total — flag risk ``


15. Cycle intelligence 🟡 (researched design — June 2026)

The cycle work is bigger than one water-offset number. It spans who has a cycle to model, a health safeguard, where you are right now, symptom logging, learning from past months, and education. Built on the menstrual-cycle science (§7/§14.3) plus the sources below.

Sources: Elliott-Sale et al. (cycle methodology); Menstrual Cycle and Hormonal Contraceptives in Female Athletes: Should Symptoms and Nutrition Matter More than Cycle Phase? (Nutrients 2026, doi 10.3390/nu18071144); IOC RED-S consensus (2014/2018/2023); ACSM Female Athlete Triad; PMC9724109 (RED-S female athlete); PMC7937612 / PMC8281678 (MC & contraception vs strength).

Guiding principle (from the 2026 review): individual, logged symptom & weight patterns should outweigh textbook phase math. Generic phase recommendations are applied **cautiously, and only once a consistent personal pattern is documented.* This is the spine of §15.4 (learning).

15.1 Cycle mode — three states, set at onboarding & editable

The phase model only applies to one of these. Captured at GS_09A, editable in Cycle settings.

ModeWhoWhat the app does
Natural cycleEumenorrheic, no hormonal contraceptionFull phase model (§7.1): water offset, undulating plan, buffer. Refined by learning (§15.4).
Hormonal contraceptionPill / patch / ring / hormonal IUD / implant / injectionNo natural-phase model — HC suppresses endogenous fluctuation. Default flat (0 offset). If the method has a withdrawal/placebo week the user can flag it; otherwise rely on logged symptoms only. Effects are modest & highly individual — never assume.
Absent / irregularNo period, post-menopause, pregnancy, or irregularNo phase model. If "absent" is unexpected → RED-S safeguard (§15.2). Irregular cycles fall back to symptom + learned patterns, not calendar prediction.

🟡 Default offset for HC and Absent modes is 0 kg until the athlete's own data says otherwise.

15.2 The RED-S safeguard ⚠️ (health-critical — non-negotiable)

Combat & weight-category sports carry elevated RED-S risk (low energy availability), and losing your period is a primary warning sign, not a convenience for the model.

note: a lost/irregular period during a hard cut can signal low energy availability (RED-S).

  1. Recommend a check-in with a doctor / sports physician. Provide an education piece (§15.5).
  2. Soften, don't push: if RED-S risk is flagged, the app must not suggest a faster cut or a bigger deficit; bias toward the conservative end and the feasibility outs (§14.6).
  3. 🔴 Product decision needed: how forcefully to intervene (gentle nudge vs. hard gate that pauses aggressive-cut features until acknowledged). Recommend at least a one-time acknowledgement gate.
  4. ⚠️ This is a wellness signal, not a diagnosis — wording must avoid alarm and avoid medical claims.

15.3 "Where am I?" — phase indicator + symptom logging

than pure prediction) and resets the amenorrhea counter.

  1. Feed learning (§15.4) — symptoms + the weight swing on those days teach the personal model.
  2. Predicted vs confirmed: calendar prediction is a guess; a logged bleed is truth. Always prefer confirmed. Surface "period expected ~Fri" as a soft prediction the athlete can confirm or correct.

15.4 Learning — get smarter each month 🟡 (the headline feature)

Rather than holding the §7 constants forever, personalise from the athlete's own logged history (weight swings aligned to confirmed cycle days, plus symptoms). This is exactly what the 2026 review argues for.

`` For each completed, confirmed cycle: alignedSwing[phase] = mean(trend-detrended weight) within that phase // remove the cut trend first learnedOffsetKg(phase) = weightedMean(alignedSwing[phase] over last N cycles) // recent cycles weighted higher learnedPeakDay = cycle day of the athlete's observed water maximum confidence = f(number of confirmed cycles, consistency of pattern) ``

15.5 Education pieces (Learn tab)

Short, coach-toned, sport-specific. Each ties to a moment in the app:

15.6 What to build (prototype)

  1. Cycle mode selector (natural / contraception / absent) driving the engine (§15.1).
  2. Phase indicator card + symptom check-in sheet (§15.3).
  3. RED-S safeguard state on the Cycle screen + its education piece (§15.2/§15.5).
  4. "Learned from your cycles" surface — learned offset/peak with confidence, vs population default (§15.4).
  5. Learn-tab education entries (§15.5).

16. Maintenance / no-deadline mode 🟡 (researched design — June 2026) — resolves F7

When there's no fight date, the countdown engine (projection cone, pace gauge, adaptive goal) has nothing to anchor to. Maintenance mode replaces it. Weight-only — this app is about making weight on the scale, so no body-composition input here.

Sources: ISSN 2024 position stand, Nutrition and weight-cut strategies for MMA & combat sports (PMC11894756); Weight cycling in combat sports: 25 years of evidence (BMC, PMC8670259); Weight loss in combat sports (J Int Soc Sports Nutr, 1550-2783-9-52); Physiological Perturbations: Weight Cycling & Metabolic Function (PMC10890020).

16.1 Three no-deadline users (all supported)

UserHas division?Maintenance target
Off-seasonyesRecommend a band from the division; they confirm/adjust.
No fight bookedyesSame as off-season — stay fight-ready.
General / no divisionnoFully self-set goal weight or range; no division math.

16.2 The maintenance band — self-set, with a recommendation + reasoning

16.3 What replaces gauge + projection (no date) — band adherence + readiness

Both signals, no countdown:

  1. Band adherence — where today's trend sits in the maintenance band.
  2. Readiness"from today, a safe cut to [division] takes ~X weeks at ≤ 1 %/wk." `` readinessWeeks = max(0, (currentTrend − bodyTarget) / (currentTrend × 1%)) `` Always tells the athlete the standing cost of getting back to weight — the no-deadline analogue of the projection.

16.4 Anti-cycling guardrail — gentle nudges + education (✅)

16.5 Weigh-in cadence (✅)

16.6 Transitions — manual, with prompts (✅)

16.7 Learning opportunities (surface, don't lecture)

Maintenance is a teaching moment between camps. Where appropriate, attach short education: the maintenance-band reasoning (16.2), the anti-cycling piece (16.4), and "what your walk-around weight says about your division" — all in the calm, coach-toned Learn style (§15.5).

16.8 What to build (prototype)

  1. Maintenance Today state (no countdown) — band adherence + readiness readout.
  2. Maintenance band card with the self-set target + recommendation/reasoning.
  3. Anti-cycling nudge (gentle, education-linked) when drifting high.
  4. Cadence option (daily ↔ weekly) in settings.
  5. Transition prompt (camp↔maintenance confirm).
  6. Learn entries (16.7).

17. Per-sport rules & guidance — sourced (June 2026)

The experience should feel bespoke to each sport: the weigh-in timing, equipment, re-weigh rule and the performance reason behind the cut all differ. This section is the sourced source-of-truth.

17.1 Confidence legend

17.2 Weigh-in & rules by sport

SportWeigh-in timingEquipmentRe-weigh / hydrationPlan typeConf.
BoxingAmateur: same-day; Pro: day beforenone (underwear/shorts)amateur uses same-day weigh-ins to curb cyclingamateur → walk-it-down; pro → camp🟢
MMADay before (a.m.); some promotions add hydration tests (ONE Championship)noneregain typically 8–15 lb / ~4–8% bw; some orgs cap/ test hydrationcamp (water cut viable)🟢
Muay ThaiNo universal standard — varies by sanctioning body; pros ~24h before, amateurs (IFMA) same-daynone (fight attire)varies; ONE ≤5% regainfree-entry goal weight; same-day → walk-it-down🟢
BJJ (IBJJF)Same-day, in the gi, immediately before you competegi (weighed dressed)single weigh-in, no tolerance, no re-weighminimal water cut🟢
Taekwondo (WT)Day before + random same-day controldobok (gear)random control ≤ +5 % of category limit → DQ (WT Competition Rules Art. 9 §2.2, confirmed Jun 2026)camp🟢
Judo (IJF)Day before (since 2017) + random comp-day controljudogi (gear)random control ≤ +5 % of category limitcamp🟢
Wrestling (UWW)Same-day, morning of competition, in singlet; multi-day events re-weigh each morningnone (singlet)no tolerance; same-day → almost no rehydration windowwalk-it-down🟢

Sources: World Boxing Competition Rules (Nov 2024, in force 1 Jan 2025); amateur same-day weigh-in practice (World Boxing / Olympic). IJF 2017 rule change — day-before official weigh-in + random competition-day control allowing ≤5 % above the category upper limit (Ceylan/ScienceDirect S2211266925000830; PMC10484915). World Taekwondo Olympic categories (olympics.com; WT) + random weigh-in +5 % tolerance — confirmed Jun 2026 against WT Competition Rules Article 9 §2.2 ("the random weigh-in shall be conducted with plus 5% tolerance of the contestant's weight category"; random check on the morning of competition; plus-categories excluded; no 2nd attempt). UWW senior freestyle categories + same-day weigh-in (uww.org, re-confirmed Jun 2026). ISSN 2024 position stand (PMC11894756) for MMA regain & hydration.

17.3 Division tables (current best, with confidence)

17.4 Performance & cut guidance per sport (the why, sourced)

General anchors (apply to all): safe loss 0.5–1.0 %/wk (§5/§14.1); acute fight-week water only where a rehydration window exists, ≤5 % bw (§14.5); combat & weight-class sports carry elevated RED-S / weight-cycling risk (§15.2). Per-sport emphasis:

17.5 Verification status

🟢 All seven sports verified against governing-body rules / peer-reviewed literature: Boxing (World Boxing 2025), MMA (ABC Unified Rules), BJJ gi + no-gi (IBJJF, men + women), Judo (IJF 2017 + 5% control), Wrestling (UWW senior freestyle), Taekwondo (WT Olympic + +5 % random control, confirmed vs WT Competition Rules Art. 9 §2.2), Muay Thai (confirmed no universal standard → free-entry). Implementation cross-check is logged in OnWeight - Rules Verification.md.

Open items for human sign-off:

(Resolved Jun 2026: Taekwondo +5 % tolerance — confirmed vs WT Competition Rules Art. 9 §2.2. BJJ women's-gi rooster — confirmed 48.5 kg, Heavy 79.3 kg vs current IBJJF tables.)


18. Additions since the core flows were written (June 2026)

These areas were designed after §1–§17 and are live in OnWeight - All Screens.html. They don't change the cut logic above; they make the product launch-ready. Each is documented here so this file stays the single source of truth.

18.1 Lexicon — "goal" → "limit" (app-wide)

The athlete-facing word for the fight-day scale number is "limit" (the weight you must hit), not "goal weight." The onboarding screen reads "Your limit / The weight you must hit on the scale," and charts label the line LIMIT. Rationale: a fighter doesn't aspire to the number, they're bound by it — "limit" carries the consequence "goal" doesn't. Code/field names stay goalWeight, bodyTarget, scaleTarget (changing them risks regressions); only display copy uses "limit." Any new copy must follow this — see OnWeight - Copy Rules.html §5 lexicon.

18.2 Accounts & safety (fc-account-safety.jsx) — launch-blockers

The returning-user / legal-gate screens onboarding never covered:

Placement: account creation happens at purchase (§10, Flow 1 hinge); the safety disclaimer and age gate are part of that account step. 🔴 Product decision: exact ordering of disclaimer vs. payment.

18.3 Legal & data rights (fc-legal.jsx)

In-app, readable Terms of Service and Privacy Policy (numbered sections, including a real Health & safety clause: "OnWeight is guidance, not medical advice… you use your plan at your own discretion"), plus data rights controls — export my data and delete my account/data. Needed for App Store / Play compliance and GDPR-style requests.

18.4 Imperial / metric parity (fc-units.jsx + fc-imperial.jsx)

A central OWUnits conversion + formatting engine so every weight renders in kg or lb from one setting — no hardcoded units. fc-imperial.jsx demonstrates the key screens in lb (US/UK athletes, and the lb-native division ladders e.g. MMA/ABC). Rule: never hardcode a unit string; format through OWUnits. Division tables stay canonical in their governing-body unit and convert for display.

18.5 Cut-strategy info sheets (fc-strategy-info.jsx) — restored from Figma GS_06A_Info

Each fight-week strategy (§8) now has a tap-through ⓘ explainer bottom sheet: Low Fibre · Low Sodium · Sweat Out · Low Carb · Water Load. Each sheet carries headline · how much can you lose? · how do you do it (food examples / dosages) · warning, with the safety ceilings stated inline (e.g. Sweat Out: never more than 5 % of body weight; stop if dizzy/faint). These restore content that had survived only as one-line card descriptions.

18.6 Widgets (fc-widgets.jsx) — post-launch retention surface

Home Screen (small + medium) and Lock Screen complications showing the cut at a glance — weight, on-track state, days/■ to weigh-in — without opening the app. Design-for-sign-off; not a logic change.

18.7 Documentation coverage note

The §10 flow maps predate 18.2–18.3. When the onboarding/camp flow diagrams are next revised, splice in: account creation + safety disclaimer + age gate at the paywall hinge, and a settings → legal / data-rights branch. Tracked here so the omission is explicit, not silent.

18.8 BFM design-audit changes (Jun 2026) — see OnWeight - BFM Audit (read).html

A start-to-finish Built for Mars critique drove a round of fixes; all are live in the prototype and All Screens (shared JSX) unless noted, with the source-of-truth and flow maps updated to match.

Onboarding / paywall (fc-onboarding.jsx, fc-screens-b.jsx):

Activation (fc-empty.jsx + prototype routing):

Daily loop (fc-screens-a.jsx):

Cycle (fc-engine.jsx):

Future-state concepts (fc-future.jsx, in the All Screens "Future · sandbox" section only — never wired from a live screen, per the launch-point rule):

Still open (business / content, not design): final trial length + price; annual-only vs annual+monthly; and replacing the labelled placeholders (social-proof fighters/quotes, win-back & widget pricing) with verified content before launch.

17.6 Changelog

OnWeight HQ